import { IsString, IsNumber, IsArray, IsOptional, IsBoolean, IsEnum, ValidateNested, Min, Max, Allow } from 'class-validator';
import { Type } from 'class-transformer';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';

export class ContentBlockDto {
  @ApiProperty({ enum: ['text', 'image', 'tool_use', 'tool_result', 'thinking'] })
  @IsString()
  type: 'text' | 'image' | 'tool_use' | 'tool_result' | 'thinking';

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  text?: string;

  @ApiPropertyOptional()
  @IsOptional()
  source?: {
    type: 'base64';
    media_type: string;
    data: string;
  };

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  name?: string;

  @ApiPropertyOptional()
  @IsOptional()
  input?: any;

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  tool_use_id?: string;

  @ApiPropertyOptional()
  @IsOptional()
  content?: string;

  @ApiPropertyOptional()
  @IsOptional()
  @IsBoolean()
  is_error?: boolean;
}

export class MessageDto {
  @ApiProperty({ enum: ['user', 'assistant'] })
  @IsEnum(['user', 'assistant'])
  role: 'user' | 'assistant';

  @ApiProperty({ 
    description: 'Message content as string or array of content blocks',
    oneOf: [
      { type: 'string' },
      { type: 'array', items: { $ref: '#/components/schemas/ContentBlockDto' } }
    ]
  })
  @Allow()
  content: string | ContentBlockDto[];
}

export class ToolDto {
  @ApiProperty()
  @IsString()
  name: string;

  @ApiProperty()
  @IsString()
  description: string;

  @ApiProperty()
  @Allow()
  input_schema: {
    type: 'object';
    properties: Record<string, any>;
    required?: string[];
  };
}

export class ToolChoiceDto {
  @ApiProperty({ enum: ['auto', 'any', 'tool', 'none'] })
  @IsEnum(['auto', 'any', 'tool', 'none'])
  type: 'auto' | 'any' | 'tool' | 'none';

  @ApiPropertyOptional()
  @IsOptional()
  @IsString()
  name?: string;
}

export class ThinkingDto {
  @ApiProperty()
  @IsBoolean()
  enabled: boolean;
}

export class CreateMessageDto {
  @ApiProperty({ description: 'Model identifier', example: 'claude-sonnet-4-20250514' })
  @IsString()
  model: string;

  @ApiProperty({ description: 'Maximum tokens to generate', minimum: 1, example: 1024 })
  @IsNumber()
  @Min(1)
  max_tokens: number;

  @ApiProperty({ type: [MessageDto], description: 'Array of input messages' })
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => MessageDto)
  messages: MessageDto[];

  @ApiPropertyOptional({ description: 'System prompt' })
  @IsOptional()
  system?: string | ContentBlockDto[];

  @ApiPropertyOptional({ description: 'Temperature for randomness', minimum: 0, maximum: 1 })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(1)
  temperature?: number;

  @ApiPropertyOptional({ description: 'Top-K sampling parameter', minimum: 0 })
  @IsOptional()
  @IsNumber()
  @Min(0)
  top_k?: number;

  @ApiPropertyOptional({ description: 'Top-P sampling parameter', minimum: 0, maximum: 1 })
  @IsOptional()
  @IsNumber()
  @Min(0)
  @Max(1)
  top_p?: number;

  @ApiPropertyOptional({ type: [String], description: 'Custom stop sequences' })
  @IsOptional()
  @IsArray()
  @IsString({ each: true })
  stop_sequences?: string[];

  @ApiPropertyOptional({ description: 'Enable streaming response' })
  @IsOptional()
  @IsBoolean()
  stream?: boolean;

  @ApiPropertyOptional({ type: [ToolDto], description: 'Available tools' })
  @IsOptional()
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => ToolDto)
  tools?: ToolDto[];

  @ApiPropertyOptional({ type: ToolChoiceDto, description: 'Tool choice strategy' })
  @IsOptional()
  @ValidateNested()
  @Type(() => ToolChoiceDto)
  tool_choice?: ToolChoiceDto;

  @ApiPropertyOptional({ type: ThinkingDto, description: 'Extended thinking configuration' })
  @IsOptional()
  @ValidateNested()
  @Type(() => ThinkingDto)
  thinking?: ThinkingDto;

  @ApiPropertyOptional({ description: 'Container identifier' })
  @IsOptional()
  @IsString()
  container?: string;

  @ApiPropertyOptional({ description: 'MCP servers configuration' })
  @IsOptional()
  @IsArray()
  mcp_servers?: any[];

  @ApiPropertyOptional({ description: 'Request metadata' })
  @IsOptional()
  metadata?: Record<string, any>;

  @ApiPropertyOptional({ enum: ['auto', 'standard_only'], description: 'Service tier' })
  @IsOptional()
  @IsEnum(['auto', 'standard_only'])
  service_tier?: 'auto' | 'standard_only';
}

export class CountTokensDto extends CreateMessageDto {
  // Inherits all properties from CreateMessageDto
  // Used specifically for the count-tokens endpoint
}

export class UsageDto {
  @ApiProperty({ description: 'Number of input tokens' })
  input_tokens: number;

  @ApiProperty({ description: 'Number of output tokens' })
  output_tokens: number;

  @ApiPropertyOptional({ description: 'Cache creation input tokens' })
  cache_creation_input_tokens?: number;

  @ApiPropertyOptional({ description: 'Cache read input tokens' })
  cache_read_input_tokens?: number;

  @ApiPropertyOptional({ description: 'Service tier used for the request' })
  service_tier?: string;
}

export class MessageResponseDto {
  @ApiProperty({ description: 'Message ID' })
  id: string;

  @ApiProperty({ enum: ['message'] })
  type: 'message';

  @ApiProperty({ enum: ['assistant'] })
  role: 'assistant';

  @ApiProperty({ type: [ContentBlockDto], description: 'Response content blocks' })
  content: ContentBlockDto[];

  @ApiProperty({ description: 'Model used for generation' })
  model: string;

  @ApiProperty({ 
    enum: ['end_turn', 'max_tokens', 'stop_sequence', 'tool_use', 'pause_turn', 'refusal'],
    description: 'Reason for stopping generation'
  })
  stop_reason: 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use' | 'pause_turn' | 'refusal';

  @ApiProperty({ description: 'Stop sequence that triggered stopping', nullable: true })
  stop_sequence: string | null;

  @ApiProperty({ type: UsageDto, description: 'Token usage information' })
  usage: UsageDto;

  @ApiPropertyOptional({ description: 'Container information' })
  container?: any;
}

// Query parameters for Messages API
export class MessagesQueryDto {
  @ApiPropertyOptional({ description: 'Enable beta features', example: true })
  @IsOptional()
  @IsBoolean()
  beta?: boolean;

  // TODO: Add handling for beta parameter in request processing
  // TODO: Implement beta-specific feature logic
}

// Extended headers for Anthropic API requests
export interface AnthropicExtendedHeaders extends Record<string, string> {
  // Standard Anthropic headers
  'x-api-key'?: string;
  'anthropic-version'?: string;
  
  // Beta and experimental features
  'anthropic-beta'?: string; // e.g., "fine-grained-tool-streaming-2025-05-14"
  'anthropic-dangerous-direct-browser-access'?: string;
  
  // Client identification headers (from Stainless SDK)
  'X-Stainless-Lang'?: string;
  'X-Stainless-Package-Version'?: string;
  'X-Stainless-OS'?: string;
  'X-Stainless-Arch'?: string;
  'X-Stainless-Runtime'?: string;
  'X-Stainless-Runtime-Version'?: string;
  'X-Stainless-Retry-Count'?: string;
  'X-Stainless-Timeout'?: string;
  'x-stainless-helper-method'?: string;
  
  // Application context headers
  'x-app'?: string; // e.g., "cli"
  
  // Standard HTTP headers
  'User-Agent'?: string;
  'Content-Type'?: string;
  'Accept'?: string;
  'Authorization'?: string;
  
  // TODO: Add processing logic for beta headers (anthropic-beta, anthropic-dangerous-direct-browser-access)
  // TODO: Add forwarding logic for X-Stainless-* headers to preserve client context
  // TODO: Add validation for x-app header values
}

export class CountTokensResponseDto {
  @ApiProperty({ description: 'Number of input tokens' })
  input_tokens: number;
}